﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace GenericWin
{
    /// <summary>
    /// Logique d'interaction pour GenericMenu.xaml
    /// </summary>
    public partial class GenericMenu : UserControl
    {
        #region Attribut(s)

        /// <summary>
        /// List de collection observable contenant les éléments du menus
        /// </summary>
        private ObservableCollection<MenuItemViewModel> _Menus;

        /// <summary>
        /// Instance la fenetre d'application mère
        /// </summary>
        private GenericApplication genericApplication;

        #endregion

        #region Propriété(s)

        /// <summary>
        /// Getter / Setter de l'application mère
        /// </summary>
        public GenericApplication GenericApplication
        {
            get
            {
                return genericApplication;
            }
            set
            {
                genericApplication = value;
                MakeMenu(_Menus.Concat((new List<MenuItemViewModel>()).ToArray()).ToList());
            }
        }

        #endregion

        #region Constructeur(s)

        /// <summary>
        /// Constructeur vide
        /// </summary>
        public GenericMenu()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Constructeur prenant en paramètre les éléments du menu à afficher
        /// </summary>
        /// <param name="menu"></param>
        public GenericMenu(List<MenuItemViewModel> menu)
            : this()
        {
            _Menus = (ObservableCollection<MenuItemViewModel>)FindResource("Menu");
            BuildMenu(menu);
        }

        #endregion

        #region Méthode(s)

        /// <summary>
        /// Construit le menu.
        /// </summary>
        /// <param name="menu">Elements du menu à intégrer dans la barre de menu</param>
        private void BuildMenu(List<MenuItemViewModel> menu)
        {
            if (menu != null)
            {
                // Ajout des menus
                foreach (MenuItemViewModel m in menu)
                {
                    _Menus.Add(m);
                }

                // Affectation des command
                foreach (MenuItemViewModel m in IterateMenus())
                {
                    m.Command = new ItemCommand(GenericApplication, m);
                }
            }
        }

        /// <summary>
        /// Permet de construire le menu. fait appel à BuildMenu.
        /// Si le menu n'est pas encore initialisé, elle le fait.
        /// </summary>
        /// <param name="menu"></param>
        public void MakeMenu(List<MenuItemViewModel> menu)
        {
            if (_Menus == null)
                _Menus = (ObservableCollection<MenuItemViewModel>)FindResource("Menu");

            _Menus.Clear();
            BuildMenu(menu);
        }

        #endregion

        #region InnerClass Command

        /// <summary>
        /// InnerClass de command, permettant de faire le lien avec les événements du clic de la souris d'un utilisateur
        /// </summary>
        private class ItemCommand : ICommand
        {
            public ItemCommand(GenericApplication owner, MenuItemViewModel menu)
            {
                Owner = owner;
                Menu = menu;
            }

            public bool CanExecute(object parameter)
            {
                return true;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                if (Owner != null)
                    Owner.ActionMenu(Menu);
            }

            public MenuItemViewModel Menu { get; set; }

            public GenericApplication Owner { get; set; }
        }

        #endregion

        #region Recursive Iterate Menu

        /// <summary>
        /// Génére un item et descent dans les la hiérarchie des éléments
        /// </summary>
        private static IEnumerable<MenuItemViewModel> IterateMenu(MenuItemViewModel m)
        {
            return (new[] { m })
                .Concat(m.Children.SelectMany(IterateMenu));
        }

        /// <summary>
        /// Génére le menu en entier et sa hiérarchie
        /// </summary>
        /// <returns></returns>
        private IEnumerable<MenuItemViewModel> IterateMenus()
        {
            return _Menus.SelectMany(IterateMenu);
        }

        #endregion
    }
}
